package info.hexin.mvc.handler.process;

import info.hexin.ioc.IocBean;
import info.hexin.log.Log;
import info.hexin.log.Logs;
import info.hexin.mvc.annotation.ViewType;
import info.hexin.mvc.handler.RequestContext;
import info.hexin.mvc.methodtree.Arg;
import info.hexin.mvc.methodtree.MethodInfo;
import info.hexin.mvc.methodtree.ViewInfo;
import info.hexin.mvc.view.ViewModel;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;

/**
 * 
 * @author hexin
 *
 */
public abstract class AbstractReequestProcess implements RequestProcess {
    private static final Log logger = Logs.get();

    /**
     * 处理request主要入口，一般不需要覆盖，覆盖的话就会导致混乱
     */
    public void process(RequestContext requestContext) throws IOException {
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();
        MethodInfo methodInfo = requestContext.getMethodInfo();
        if (methodInfo == null) {
            try {
                response.sendError(404, "mapping error!!");
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 验证没有问题，开始处理request
        List<Object> argsValue = new ArrayList<Object>();
        doMethodParam(request, response, methodInfo.getArgs(), argsValue);
        methodExec(request, response, methodInfo, argsValue);
    }

    /**
     * 
     * 根据request和response封装method需要的参数
     * 
     * @param request
     * @param response
     * @param args
     *            所需要参数列表
     * @param argList
     *            参数值对象，method反射调用传进去的参数列表
     */
    public abstract void doMethodParam(HttpServletRequest request, HttpServletResponse response, List<Arg> args,
            List<Object> argList) throws IOException;

    /**
     * 反射调用method，感觉这个方法还是需要拆分，反射调用应该提上来<br>
     * 没有将视图拆分开来，感觉视图添加比较麻烦
     * 
     * @param request
     * @param response
     * @param methodInfo
     */
    public void methodExec(HttpServletRequest request, HttpServletResponse response, MethodInfo methodInfo,
            List<Object> argList) throws IOException {
        IocBean iocBean = methodInfo.getIocBean();
        methodInfo.getMethod();
        java.lang.reflect.Method reflectMethod = methodInfo.getReflectMethod();
        try {
            //TODO 增加生命周期
            Object result = reflectMethod.invoke(iocBean.getInstance(), argList.toArray());
            ViewInfo viewInfo = methodInfo.getViewInfo();

            // 是否使用了view注解进行标记返回值
            if (viewInfo != null) {
                if (viewInfo.getViewType() == ViewType.JSON) {
                    responseJson(response,result);
                } else if (viewInfo.getViewType() == ViewType.JSP) {
                    if (result instanceof String) {
                        String path = result.toString();
                        if (!path.endsWith(".jsp")) {
                            path = path + ".jsp";
                        }
                        if (path.startsWith("redirect:")) {
                            path = path.substring(9);
                            response.sendRedirect(path);
                        } else {
                            request.getRequestDispatcher(path).forward(request, response);
                        }
                    }
                }
            } else if (result instanceof ViewModel) {
                logger.error(" 返回值为view");
                ViewModel view = (ViewModel) result;
                view.render(request, response);
            } else {
                responseJson(response,result);
                logger.error(" not sure response type!! will response json .");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void responseJson(HttpServletResponse response,Object result) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        PrintWriter out = response.getWriter();
        String json = JSON.toJSONString(result);
        logger.debug("method result json  >>>>>>  {}", json);
        out.append(json);
        out.flush();
        out.close();
    }
}
